package com.waimai1.waimai.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.waimai1.waimai.common.AesUtil;
import com.waimai1.waimai.common.BaseContext;
import com.waimai1.waimai.common.R;
import com.waimai1.waimai.common.Utils;
import com.waimai1.waimai.config.PartnerPayConfig;
import com.waimai1.waimai.config.PayConfig;
import com.waimai1.waimai.entity.*;
import com.waimai1.waimai.exception.EnumException;
import com.waimai1.waimai.exception.NotErrorException;
import com.waimai1.waimai.service.*;
import com.wechat.pay.java.core.cipher.PrivacyDecryptor;
import com.wechat.pay.java.core.cipher.RSAPrivacyDecryptor;
import com.wechat.pay.java.core.notification.Notification;
import com.wechat.pay.java.core.notification.Resource;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.refund.model.Refund;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.*;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Target;
import java.math.BigDecimal;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.util.*;

@Slf4j
@RestController
@RequestMapping("/wepay")
public class PayController {
//    @Value("${wxPay.appid}")
//    private String appid;
    @Value("${wxPay.apiV3key}")
    private String apiV3key;
    @Value("${wxPay.partnerApiV3key}")
    private String partnerApiV3key;
    @Autowired
    private WepayService wepayService;
    @Autowired
    private PinpaiService pinpaiService;
    @Autowired
    private LocalWepayService localWepayService;
    @Autowired
    private WepayOrderService wepayOrderService;
    @Autowired
    private HwService hwService;
    @Autowired
    private MyOrderService orderService;
    @Autowired
    private MHService MHService;
    @Autowired
    private UserService userService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private AcidService acidService;
    @Autowired
    private FlService flService;
    @PostMapping("/prepay")
    public R<Object> pay(@RequestBody Map<String, Object> mapreq) throws IOException, NoSuchAlgorithmException, InvalidKeyException, SignatureException {
        LambdaQueryWrapper<MyOrder> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        orderLambdaQueryWrapper.eq(MyOrder::getAcid,BaseContext.getAcid()).eq(MyOrder::getOutTradeNo,  mapreq.get("outTradeNo"));
        MyOrder order = orderService.getOne(orderLambdaQueryWrapper, false);
//        如果是品牌订单则获取品牌优惠goodtag
        String goodtag="";
        if("PP".equals(order.getOutTradeNo().substring(0,2))||"FL".equals(order.getOutTradeNo().substring(0,2))){
            LambdaQueryWrapper<Pinpai> pinpaiLambdaQueryWrapper = new LambdaQueryWrapper<>();
            pinpaiLambdaQueryWrapper.eq(Pinpai::getBrandId, order.getBrandId());
            Pinpai pp = pinpaiService.getOne(pinpaiLambdaQueryWrapper);
            if(null!=pp){
                goodtag=pp.getGoodtag();
            }
        }
        //义乌的电影需要加金卡标志
        if("DY".equals(order.getOutTradeNo().substring(0,2))&&BaseContext.getAcid()==15){
            //金卡用户
            if("ptk".equals(mapreq.get("card"))){
                User user= userService.getUserByOpenid();
                Boolean flag = redisTemplate.opsForSet().isMember("YIWU:movieWhite", user.getPhone());
                if(flag){
                    goodtag="ptkyh";
                }else{
                    goodtag="jkyh";
                }
            }else{
                goodtag="jkyh";
            }
        }
        //成泰
        if("DY".equals(order.getOutTradeNo().substring(0,2))&&BaseContext.getAcid()==14){
            goodtag="ctdyy";
        }
        Integer totalFee=(int)Math.round(order.getTotalPrice()*100);
        PrepayResponse response = wepayService.prepay(totalFee, BaseContext.getopenId(), (String) mapreq.get("outTradeNo"), goodtag);
        String now = String.valueOf(new Date().getTime()).substring(0, 10);
        String nonceStr = String.valueOf(Math.random()).replace(".", "");
        Acid resAcid=acidService.getById(BaseContext.getAcid());
        String[] params = {resAcid.getAppid(), now, nonceStr, "prepay_id=" + response.getPrepayId()};
        String sign = Utils.getWeSign(params, PayConfig.getPath());
        Map<String, String> map = new HashMap<>();
        map.put("timestamp", now);
        map.put("nonceStr", nonceStr);
        map.put("prepayId", "prepay_id=" + response.getPrepayId());
        map.put("sign", sign);
        return R.success(map);
    }

    @PostMapping("/localPrepay")
    public R<Object> localPrepay(@RequestBody Map<String, Object> mapreq) throws IOException, NoSuchAlgorithmException, InvalidKeyException, SignatureException {
        String now = String.valueOf(new Date().getTime()).substring(8);
        String tradeNo = (String) mapreq.get("tradeNo");
//        通过outradeNo获取totalfee
        LambdaQueryWrapper<MyOrder> orderLambdaQueryWrapper=new LambdaQueryWrapper<>();
        orderLambdaQueryWrapper.eq(MyOrder::getAcid,BaseContext.getAcid()).eq(MyOrder::getOutTradeNo,tradeNo);
        MyOrder order=orderService.getOne(orderLambdaQueryWrapper);
        if(null==order){
            throw new NotErrorException(EnumException.NO_ORDER);
        }
        Integer totalFee=(int)Math.round(order.getTotalPrice()*100);
        Integer shopId = (Integer) mapreq.get("shopId");
//        是否需要分账
        boolean fenzhang=false;
        if("社团".equals(order.getRemark())){
            fenzhang=true;
        }
        com.wechat.pay.java.service.partnerpayments.jsapi.model.PrepayResponse response = localWepayService.localPrepay(totalFee, BaseContext.getopenId(), tradeNo, shopId,fenzhang);
        String nonceStr = String.valueOf(Math.random()).replace(".", "");
        Acid resAcid=acidService.getById(BaseContext.getAcid());
        String[] params = {resAcid.getAppid(), now, nonceStr, "prepay_id=" + response.getPrepayId()};
        String sign = Utils.getWeSign(params, PartnerPayConfig.getPath());
        //获取appid
        Acid acidres=acidService.getById(BaseContext.getAcid());
        Map<String, String> map = new HashMap<>();
        map.put("appid",acidres.getAppid());
        map.put("timestamp", now);
        map.put("nonceStr", nonceStr);
        map.put("prepayId", "prepay_id=" + response.getPrepayId());
        map.put("sign", sign);
        return R.success(map);
    }
    @GetMapping("/prepay/{id}")
    public R<Transaction> queryByWeiId(@RequestBody String id){
        Transaction response = wepayService.queryOrderById(id);
        return R.success(response);
    }
    @PostMapping("/createHwOrder")
    public void createHwOrder(@RequestBody Map<String, String> map) throws UnsupportedEncodingException {
        String tradeNo = map.get("tradeNo");
        String productsJson = map.get("products");
        LambdaQueryWrapper<MyOrder> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(MyOrder::getAcid,BaseContext.getAcid()).eq(MyOrder::getOutTradeNo, tradeNo);
        //创建hw订单
        MyOrder order = orderService.getOne(queryWrapper);
        if (tradeNo.contains("DY")) {
            hwService.createOrder(order.getHwOrderId());
        } else {
            hwService.createOrder(order.getBrandId(), order.getRestaurantId(), order.getTakePhone(), order.getEatType(), productsJson, tradeNo);
        }
    }

    @PostMapping("/partnerNotify")
    public String partnerNotify(HttpServletRequest request, HttpServletResponse httpResponse) throws Exception {
        //判断是否支付成功，如果成功则写入订单表，修改状态，如果失败则不操作
        log.info(request.toString());
        JSONObject resourceObj = wepayService.getResource(request, partnerApiV3key);
        if (null != resourceObj) {
            // 如果微信支付单存在，则已经处理过
            LambdaQueryWrapper<WepayOrder> wepayOrderLambdaQueryWrapper = new LambdaQueryWrapper<>();
            wepayOrderLambdaQueryWrapper.eq(WepayOrder::getOutTradeNo, resourceObj.getString("out_trade_no"));
            if (null == wepayOrderService.getOne(wepayOrderLambdaQueryWrapper)) {
                //创建微信支付单
                WepayOrder wepayOrder = Utils.mapToEntity(resourceObj, WepayOrder.class);
                wepayOrder.setAppid(resourceObj.getString("sp_appid"));
                wepayOrder.setMchid(resourceObj.getString("sp_mchid"));
                wepayOrder.setSubMchid(resourceObj.getString("sub_mchid"));
                wepayOrder.setPayerTotal((Integer) JSONPath.read(resourceObj.toJSONString(), "amount.payer_total"));
                wepayOrder.setTotal((Integer) JSONPath.read(resourceObj.toJSONString(), "amount.total"));
                wepayOrder.setPromotionDetail(resourceObj.getString("promotion_detail"));
                wepayOrder.setOutTradeNo(resourceObj.getString("out_trade_no"));
                wepayOrder.setTransactionId(resourceObj.getString("transaction_id"));
                wepayOrder.setTradeType(resourceObj.getString("trade_type"));
                wepayOrder.setTradeState(resourceObj.getString("trade_state"));
                wepayOrder.setBankType(resourceObj.getString("bank_type"));
                wepayOrder.setSuccessTime(resourceObj.getDate("success_time"));
                wepayOrder.setOpenid((String) JSONPath.read(resourceObj.toJSONString(), "payer.openid"));
                wepayOrderService.save(wepayOrder);

                //更新订单状态信息
//            生成取单码
                Random random = new Random(100);
                int randomWithNextInt = random.nextInt(98) + 1;
                String code = randomWithNextInt + String.valueOf(new Date().getTime()).substring(9);
                MyOrder order = new MyOrder();
                order.setOutTradeNo(resourceObj.getString("out_trade_no"));
                order.setWepayOrderId(resourceObj.getString("transaction_id"));
                order.setQrCode(code);
                order.setTicketCode(code);
                if ("SUCCESS".equals(resourceObj.getString("trade_state"))) {
                    order.setStatus(Utils.STATUS_PAYED);
                }
                LambdaQueryWrapper<MyOrder> queryWrapper = new LambdaQueryWrapper();
                queryWrapper.eq(MyOrder::getOutTradeNo, resourceObj.getString("out_trade_no"));
                if (!orderService.update(order, queryWrapper)) {
                    log.error("支付通知更新订单状态错误");
                }
            }
        }
        httpResponse.setStatus(200);
        return "ok";
    }

    @PostMapping("/notify")
    public String notify(HttpServletRequest request, HttpServletResponse httpResponse) throws Exception {
        //判断是否支付成功，如果成功则写入订单表，修改状态，如果失败则不操作
        log.info(request.toString());
        JSONObject resourceObj = wepayService.getResource(request, apiV3key);
        log.info(String.valueOf(resourceObj));
        if (null != resourceObj) {
            // 如果微信支付单存在，则已经处理过
            LambdaQueryWrapper<WepayOrder> wepayOrderLambdaQueryWrapper = new LambdaQueryWrapper<>();
            wepayOrderLambdaQueryWrapper.eq(WepayOrder::getOutTradeNo, resourceObj.getString("out_trade_no"));
            WepayOrder wepayOrder=null;
            if (null == wepayOrderService.getOne(wepayOrderLambdaQueryWrapper)) {
                //创建微信支付单
                wepayOrder = Utils.mapToEntity(resourceObj, WepayOrder.class);
                wepayOrder.setPayerTotal((Integer) JSONPath.read(resourceObj.toJSONString(), "amount.payer_total"));
                wepayOrder.setTotal((Integer) JSONPath.read(resourceObj.toJSONString(), "amount.total"));
                wepayOrder.setPromotionDetail(resourceObj.getString("promotion_detail"));
                wepayOrder.setOutTradeNo(resourceObj.getString("out_trade_no"));
                wepayOrder.setTransactionId(resourceObj.getString("transaction_id"));
                wepayOrder.setTradeType(resourceObj.getString("trade_type"));
                wepayOrder.setTradeState(resourceObj.getString("trade_state"));
                wepayOrder.setBankType(resourceObj.getString("bank_type"));
                wepayOrder.setSuccessTime(resourceObj.getDate("success_time"));
                wepayOrder.setOpenid((String) JSONPath.read(resourceObj.toJSONString(), "payer.openid"));
                wepayOrderService.save(wepayOrder);

                //更新订单状态信息
                MyOrder order = new MyOrder();
                order.setOutTradeNo(resourceObj.getString("out_trade_no"));
                order.setWepayOrderId(resourceObj.getString("transaction_id"));
                if ("SUCCESS".equals(resourceObj.getString("trade_state"))) {
                    order.setStatus(Utils.STATUS_PAYED);
                } else {
                    throw new NotErrorException(1007, resourceObj.getString("trade_state"));
                }
                LambdaQueryWrapper<MyOrder> queryWrapper = new LambdaQueryWrapper();
                queryWrapper.eq(MyOrder::getOutTradeNo, resourceObj.getString("out_trade_no"));
                orderService.update(order, queryWrapper);
//            创建hw订单
//                if (resourceObj.getString("out_trade_no").contains("DY")) {
//                    hwService.createOrder(order.getHwOrderId());
//                } else {
//                    //products信息保存在seat字段中
//                    hwService.createOrder(order.getBrandId(), order.getRestaurantId(), order.getTakePhone(), order.getEatType(), order.getSeat(), resourceObj.getString("out_trade_no"));
//                }
                order = orderService.getOne(queryWrapper);
                //如果是喜茶则创建hw订单
                //创建hw订单
                if(order.getBrandId()==19){

                        //products信息保存在seat字段中
                        hwService.createOrder(order.getBrandId(), order.getRestaurantId(), order.getTakePhone(), order.getEatType(), order.getSeat(), resourceObj.getString("out_trade_no"));

                }else{
                    //创建麻花订单
                    if (order.getHwStatus() != null){
                        throw new NotErrorException(1007, "已处理过的回调");
                    }else if (order.getOutTradeNo().startsWith("DY")) {
                        MHService.createDYOrder(order);
                    }else if (order.getOutTradeNo().startsWith("FL")) {
                        flService.createFLOrder(order);
                    } else if(order.getOutTradeNo().startsWith("PP")){
                        MHService.createOrder(order);
                    }else{
                        throw new NotErrorException(1007, "未匹配的订单类型");
                    }
                }

//            if (resourceObj.getString("out_trade_no").contains("DY")) {
//                Map<String, Object> argsMap = new HashMap<String, Object>();
//                Map<String,Object> res=(Map<String, Object>) MHService.getData(argsMap,Utils.mhUrl.get(url),time);
//                if(!"000000".equals(res.get("rtnCode"))){
//                    throw new NotErrorException(1008,res.get("rtnCode")+(String)res.get("rtnMsg"));
//                }

//                hwService.createOrder(order.getHwOrderId());
//            } else {
//                //products信息保存在seat字段中
//                hwService.createOrder(order.getBrandId(), order.getRestaurantId(), order.getTakePhone(), order.getEatType(), order.getSeat(), resourceObj.getString("out_trade_no"));
//            }
            }
        }
        httpResponse.setStatus(200);
        return "ok";
    }



    @PostMapping("/searchWepayStatus")
    public R<Transaction> searchWepayStatus(@RequestBody Map<String, String> map) throws UnsupportedEncodingException {
        Transaction searchResult = wepayService.queryOrderByOutTradeNo(map.get("outTradeNo"));
        if (searchResult.getTradeState().equals(Transaction.TradeStateEnum.SUCCESS)) {
            LambdaQueryWrapper<MyOrder> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(MyOrder::getOutTradeNo, map.get("outTradeNo"));
            MyOrder order = orderService.getOne(queryWrapper);
            order.setWepayOrderId(searchResult.getTransactionId());
            order.setStatus(Utils.STATUS_PAYED);
            orderService.update(order, queryWrapper);

            if (map.get("outTradeNo").contains("DY")) {
                hwService.createOrder(order.getHwOrderId());
            } else {
                hwService.createOrder(order.getBrandId(), order.getRestaurantId(), order.getTakePhone(), order.getEatType(), map.get("productsJson"), map.get("outTradeNo"));
            }
        }
        return R.success(searchResult);
    }

    //全额退款
    @PostMapping("/refund")
    public R<String> refund(@RequestBody MyOrder order) {
        String leixing = order.getOutTradeNo().substring(0, 2);
        order=orderService.getById(order.getId());
        if ("DY".equals(order.getOutTradeNo().substring(0, 2))) {
            //电影退款单
            wepayService.allRefund(order);
            return R.success("ok");
        } else if ("PP".equals(order.getOutTradeNo().substring(0, 2))) {
            //全额退款
            if ("出餐失败".equals(order.getHwStatus())) {
                wepayService.allRefund(order);
                return R.success("ok");
            }
            //部分退款
            if ("部分出餐".equals(order.getHwStatus())) {
                wepayService.partRefund(order);
                return R.success("ok");
            }
        } else if ("LS".equals(order.getOutTradeNo().substring(0, 2))) {
            wepayService.allRefund(order);
            return R.success("ok");
        }
        throw new NotErrorException(EnumException.NO_REFUND_APPLY);
    }

    @PostMapping("/createDYOrder")
    public R<Object> createDYOrder(@RequestBody MyOrder order) throws Exception {
        //创建订单和详情单
        String time = String.valueOf(new Date().getTime());
        String tradeNo="DY"+order.getTakePhone().substring(7)+time;
        order.setOutTradeNo(tradeNo);
        order.setStatus(Utils.STATUS_WAIT_PAY);
        //TODO 最好重新查询设置座位价格
//        JSONObject jsonObject = JSON.parseObject(order.getSeat());
//        List<Map> maps = JSON.parseArray(order.getSeat(), Map.class);
//        maps.forEach(item->{
//            item.get
//        });
//        order.setTotalPrice(100.0);
        order.setOpenid(BaseContext.getopenId());
        order.setAcid(BaseContext.getAcid());
        if(orderService.save(order)){
            //添加延时关单功能
            int delayTime=10*1000;
            redisTemplate.opsForZSet().add("cancelOrder",order.getOutTradeNo(),System.currentTimeMillis()+delayTime);
        };
//        if (!BaseContext.getPhone().equals(order.getTakePhone())) {
//            userService.updatePhone(order);
//        }
        return R.success(tradeNo);
    }
}
